
package com.jf.cloud.api.product.manager;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.jf.cloud.api.delivery.feign.DeliveryFeignClient;
import com.jf.cloud.api.product.feign.ShopCartFeignClient;
import com.jf.cloud.api.product.feign.SkuFeignClient;
import com.jf.cloud.api.product.feign.SkuStockFeignClient;
import com.jf.cloud.api.product.feign.SpuFeignClient;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.order.bo.DeliveryModeBO;
import com.jf.cloud.common.order.dto.ShopCartItemDTO;
import com.jf.cloud.common.order.vo.OrderSkuLangVO;
import com.jf.cloud.common.order.vo.OrderSpuLangVO;
import com.jf.cloud.common.order.vo.ShopCartItemVO;
import com.jf.cloud.common.order.vo.VirtualRemarkVO;
import com.jf.cloud.common.product.constant.PreSaleType;
import com.jf.cloud.common.product.constant.SpuType;
import com.jf.cloud.common.product.dto.CartComboMatchSpuDTO;
import com.jf.cloud.common.product.vo.SkuVO;
import com.jf.cloud.common.product.vo.SpuAndSkuVO;
import com.jf.cloud.common.product.vo.SpuVO;
import com.jf.cloud.common.response.ResponseEnum;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.util.Json;
import com.jf.cloud.common.util.PriceUtil;
import ma.glasnost.orika.MapperFacade;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 购物车适配器
 * @author zz
 * @date 2020/12/07
 */
@Component
public class ShopCartItemAdapter {

    private final Logger LOGGER = LoggerFactory.getLogger(ShopCartItemAdapter.class);
    @Autowired
    private SpuFeignClient spuFeignClient;

    @Autowired
    private ShopCartFeignClient shopCartFeignClient;

    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private SkuFeignClient skuFeignClient;

    @Autowired
    private SkuStockFeignClient skuStockFeignClient;

    /**
     * 获取购物项组装信息
     *
     * @param shopCartItemParam 购物项参数
     * @return 购物项组装信息
     */
    public List<ShopCartItemVO> getShopCartItems(ShopCartItemDTO shopCartItemParam, Long userId, Long addrId) {
        List<ShopCartItemVO> shopCartItems;
        // 当立即购买时，没有提交的订单是没有购物车信息的
        if (shopCartItemParam != null) {
            LOGGER.info("立即购买,处理立即购买信息");
            //套餐商品购买
            if (Objects.nonNull(shopCartItemParam.getComboId())) {
                LOGGER.info("套餐商品购买,处理套餐商品购买信息");
                return getComboShopCartItems(shopCartItemParam, userId, addrId);
            }
            shopCartItems = conversionShopCartItem(shopCartItemParam, null, userId, addrId);
        }
        // 从购物车提交订单
        else {
            LOGGER.info("从购物车提交订单,处理购物车信息");
            ServerResponseEntity<List<ShopCartItemVO>> checkedShopCartItemsResponse = shopCartFeignClient.getCheckedShopCartItems(addrId);
            if (!checkedShopCartItemsResponse.isSuccess()) {
                LOGGER.error("从购物车提交订单,处理购物车信息,获取购物车信息失败");
                throw new LuckException(checkedShopCartItemsResponse.getMsg());
            }
            shopCartItems = checkedShopCartItemsResponse.getData();
        }

        // 请选择您需要的商品加入购物车
        if (CollectionUtil.isEmpty(shopCartItems)) {
            LOGGER.info("购物车为空");
            throw new LuckException(ResponseEnum.SHOP_CART_NOT_EXIST);
        }
        // 返回购物车选择的商品信息
        return shopCartItems;
    }

    /**
     * 将参数转换成组装好的购物项
     *
     * @param shopCartItemParam 购物项参数
     * @param activityPriceFee  活动价
     * @param userId            用户id
     * @param addrId            用户收货地址id
     * @return 组装好的购物项
     */
    public List<ShopCartItemVO> conversionShopCartItem(ShopCartItemDTO shopCartItemParam, Long activityPriceFee, Long userId, Long addrId) {
        ServerResponseEntity<SpuAndSkuVO> spuAndSkuResponse = spuFeignClient.getSpuAndSkuAndRateById(shopCartItemParam.getSpuId(), shopCartItemParam.getSkuId(), false);
        if (!spuAndSkuResponse.isSuccess()) {
            throw new LuckException(spuAndSkuResponse.getMsg());
        }
        SkuVO sku = spuAndSkuResponse.getData().getSku();
        SpuVO spu = spuAndSkuResponse.getData().getSpu();

        // 拿到购物车的所有item
        ShopCartItemVO shopCartItem = getShopCartItemVO(shopCartItemParam, sku, spu);
        LOGGER.info("商家代销供应商商品且为供应商发货,设置-供应商信息:{}",spu.toString());
        // 判断下是否为供应商商品,如果是商家代销供应商商品且为供应商发货设置供应商信息
        if (!Objects.equals(spu.getSupplierId(), 0L) && Objects.equals(spu.getSupplierDeliveryType(), 1)) {
            handleSupplier(sku, shopCartItem);
            LOGGER.info("商家代销供应商商品且为供应商发货,设置供应商信息");
        } else {
            shopCartItem.setSupplierId(0L);
            shopCartItem.setTotalPurchaseAmount(0L);
            shopCartItem.setSupplierRate(0.0);
            shopCartItem.setSupplierPriceFee(0L);
            LOGGER.info("非商家代销供应商商品或者不为供应商发货,设置供应商信息为空");
        }
        shopCartItem.setSupplierId(spu.getSupplierId());
        shopCartItem.setSupplierDeliveryType(spu.getSupplierDeliveryType());
        shopCartItem.setDiscountId(0L);
        shopCartItem.setIsChecked(1);


        // 虚拟商品信息
        handleVirtual(spu, shopCartItem);

        shopCartItem.setImgUrl((Objects.nonNull(sku.getImgUrl()) && StrUtil.isNotBlank(sku.getImgUrl())) ? sku.getImgUrl() : spu.getMainImgUrl());
        shopCartItem.setSkuPriceFee(sku.getPriceFee());
        shopCartItem.setTotalAmount(shopCartItem.getCount() * shopCartItem.getSkuPriceFee());
        // 初始化商品实际金额
        shopCartItem.setActualTotal(shopCartItem.getTotalAmount());
        shopCartItem.setShareReduce(0L);
        // 如果活动价大于0则使用活动价格
        if (activityPriceFee != null && activityPriceFee > 0L) {
            // 商品实际金额,优惠金额放入店铺金额
            shopCartItem.setSkuPriceFee(activityPriceFee);
            shopCartItem.setActualTotal(shopCartItem.getCount() * activityPriceFee);
            long shareReduce = shopCartItem.getTotalAmount() - shopCartItem.getActualTotal() < 0 ? 0 : shopCartItem.getTotalAmount() - shopCartItem.getActualTotal();
            shopCartItem.setShareReduce(shareReduce);
            LOGGER.info("活动价大于0则使用活动价格");
        }

        shopCartItem.setDistributionUserId(shopCartItemParam.getDistributionUserId());
        shopCartItem.setCreateTime(new Date());
        // 物流配送信息
        shopCartItem.setDeliveryMode(spu.getDeliveryMode());
        shopCartItem.setDeliveryTemplateId(spu.getDeliveryTemplateId());

        DeliveryModeBO deliveryModeBO = Json.parseObject(shopCartItem.getDeliveryMode(), DeliveryModeBO.class);

        shopCartItem.setDeliveryModeBO(deliveryModeBO);
        shopCartItem.setShopId(spu.getShopId());
        shopCartItem.setWeight(sku.getWeight());
        shopCartItem.setVolume(sku.getVolume());
        // 预售信息
        shopCartItem.setPreSaleType(spu.getPreSaleType());
        // 如果是预售商品，处理下发货时间，定金相关优惠金额和实付金额
        if (!Objects.equals(shopCartItem.getPreSaleType(), PreSaleType.DISABLE.value())) {
            handlePreSaleInfo(shopCartItem, spu);
            LOGGER.info("预售商品，处理下发货时间，定金相关优惠金额和实付金额");
        }
//        //----旧的---判断用户的默认地址是否在配送范围内
        // 已经搬回到order服务判断
        return Collections.singletonList(shopCartItem);
    }

    private static void handleVirtual(SpuVO spu, ShopCartItemVO shopCartItem) {
        shopCartItem.setSpuMold(0);
        if (Objects.equals(spu.getSpuMold(), 1)) {
            shopCartItem.setSpuMold(spu.getSpuMold());
            shopCartItem.setIsRefund(spu.getIsRefund());
            shopCartItem.setVirtualRemark(spu.getVirtualRemark());
            shopCartItem.setWriteOffNum(spu.getWriteOffNum());
            shopCartItem.setWriteOffMultipleCount(spu.getWriteOffMultipleCount());
            shopCartItem.setWriteOffStart(spu.getWriteOffStart());
            shopCartItem.setWriteOffEnd(spu.getWriteOffEnd());
            shopCartItem.setWriteOffTime(spu.getWriteOffTime());
            if (StrUtil.isNotBlank(spu.getVirtualRemark()) && !Objects.equals(spu.getVirtualRemark(), "")) {
                List<VirtualRemarkVO> virtualRemarkList = JSON.parseArray(spu.getVirtualRemark()).toJavaList(VirtualRemarkVO.class);
                for (VirtualRemarkVO virtualRemarkVO : virtualRemarkList) {
                    if (virtualRemarkVO.getRequired() == null) {
                        virtualRemarkVO.setRequired(false);
                    }
                    virtualRemarkVO.setSpuId(shopCartItem.getSpuId());
                }
                shopCartItem.setVirtualRemarkList(virtualRemarkList);
            }
        }
    }

    private void handleSupplier(SkuVO sku, ShopCartItemVO shopCartItem) {
        shopCartItem.setSupplierRate(0.0);
        ServerResponseEntity<SpuAndSkuVO> productResponse = spuFeignClient.getSpuAndSkuAndRateById(shopCartItem.getSpuId(), shopCartItem.getSkuId(), true);
        if (!productResponse.isSuccess()) {
            throw new LuckException(productResponse.getMsg());
        }
        SpuVO spuVO = productResponse.getData().getSpu();
        SkuVO skuVO = productResponse.getData().getSku();
        shopCartItem.setSupplierId(spuVO.getSupplierId());
        shopCartItem.setDeliveryTemplateId(spuVO.getDeliveryTemplateId());
        shopCartItem.setSupplierPriceFee(skuVO.getSupplyPriceFee());
        shopCartItem.setTotalPurchaseAmount(shopCartItem.getCount() * skuVO.getSupplyPriceFee());
        shopCartItem.setSupplierSpuId(spuVO.getSupplierSpuId());
        shopCartItem.setSupplierSkuId(skuVO.getSupplierSkuId());
        shopCartItem.setSupplierRate(spuVO.getSupplierRate());
        ServerResponseEntity<SpuVO> supplierSpuResponse = spuFeignClient.getDetailById(spuVO.getSupplierSpuId());
        if (!supplierSpuResponse.isSuccess()) {
            throw new LuckException(productResponse.getMsg());
        }
        SpuVO supplierSpu = supplierSpuResponse.getData();
        shopCartItem.setSupplierSpuLangList(mapperFacade.mapAsList(supplierSpu.getSpuLangList(), OrderSpuLangVO.class));
        ServerResponseEntity<SkuVO> supplierSkuResponse = skuFeignClient.getById(sku.getSupplierSkuId());
        if (!supplierSkuResponse.isSuccess()) {
            throw new LuckException(supplierSkuResponse.getMsg());
        }
        SkuVO supplierSku = supplierSkuResponse.getData();
        shopCartItem.setSupplierSkuLangList(mapperFacade.mapAsList(supplierSku.getSkuLangList(), OrderSkuLangVO.class));
        shopCartItem.setSupplierUrl((Objects.nonNull(supplierSku.getImgUrl()) && CharSequenceUtil.isNotBlank(supplierSku.getImgUrl())) ? supplierSku.getImgUrl() : supplierSpu.getMainImgUrl());
    }

    private ShopCartItemVO getShopCartItemVO(ShopCartItemDTO shopCartItemParam, SkuVO sku, SpuVO spu) {
        ShopCartItemVO shopCartItem = new ShopCartItemVO();
        shopCartItem.setCartItemId(0L);
        shopCartItem.setSkuId(sku.getSkuId());
        shopCartItem.setPartyCode(sku.getPartyCode());
        shopCartItem.setSpuCode(spu.getSpuCode());
        shopCartItem.setCount(shopCartItemParam.getCount());
        shopCartItem.setSpuId(spu.getSpuId());
        shopCartItem.setIsCompose(spu.getIsCompose());
        shopCartItem.setCategoryId(spu.getCategoryId());
        shopCartItem.setScoreFee(sku.getScoreFee());
        shopCartItem.setRate(spu.getRate());
        shopCartItem.setSpuType(spu.getSpuType());
        shopCartItem.setSkuLangList(mapperFacade.mapAsList(sku.getSkuLangList(), OrderSkuLangVO.class));
        shopCartItem.setSpuLangList(mapperFacade.mapAsList(spu.getSpuLangList(), OrderSpuLangVO.class));
        if (Objects.equals(spu.getSpuType(), SpuType.SCORE.value())) {
            shopCartItem.setScorePrice(sku.getScoreFee() * shopCartItem.getCount());
        } else {
            shopCartItem.setScorePrice(Constant.ZERO_LONG);
        }
        return shopCartItem;
    }

    private void handlePreSaleInfo(ShopCartItemVO shopCartItem, SpuVO spu) {
        if (Objects.equals(shopCartItem.getPreSaleType(), PreSaleType.DEPOSIT.value())) {
            long depositAmount = spu.getDepositAmount() * shopCartItem.getCount();
            long depositExpansionAmount = spu.getDepositExpansionAmount() * shopCartItem.getCount();
            LOGGER.info("预售定金金额：{}，预售尾款金额：{}", depositAmount, depositExpansionAmount);
            if (Objects.equals(spu.getDepositType(), 0)) {
                depositAmount = PriceUtil.divideByBankerRounding(shopCartItem.getTotalAmount() * spu.getDepositAmount(), 10000);
                depositExpansionAmount = PriceUtil.divideByBankerRounding(shopCartItem.getTotalAmount() * spu.getDepositExpansionAmount(), 10000);
                LOGGER.info("定金收取类型为按比例收取，预售定金金额：{}，预售尾款金额：{}", depositAmount, depositExpansionAmount);
            }
            shopCartItem.setDepositAmount(depositAmount);
            shopCartItem.setActualDepositAmount(depositAmount);
            shopCartItem.setDepositExpansionAmount(depositExpansionAmount);
            shopCartItem.setDepositReduceAmount(depositExpansionAmount - depositAmount);
            shopCartItem.setBalanceAmount(shopCartItem.getTotalAmount() - depositAmount);
            shopCartItem.setActualBalanceAmount(shopCartItem.getTotalAmount() - depositExpansionAmount);
            shopCartItem.setBalanceStartTime(spu.getBalanceStartTime());
            shopCartItem.setBalanceEndTime(spu.getBalanceEndTime());
            shopCartItem.setShareReduce(shopCartItem.getDepositReduceAmount());
            shopCartItem.setActualTotal(shopCartItem.getActualTotal() - shopCartItem.getDepositReduceAmount());
        }
        shopCartItem.setPreSaleDeliveryType(spu.getPreSaleDeliveryType());
        shopCartItem.setPreSaleDeliveryTime(spu.getPreSaleDeliveryTime());
    }

    /**
     * 套餐商品
     *
     * @param orderItem
     * @return
     */
    private List<ShopCartItemVO> getComboShopCartItems(ShopCartItemDTO orderItem, Long userId, Long addrId) {
        List<ShopCartItemVO> shopCartItems = new ArrayList<>(Constant.INITIAL_CAPACITY);
        //套餐中主商品数量
        Integer mainCount = orderItem.getCount() * orderItem.getComboMainLeastNum();
        orderItem.setCount(mainCount);
        // 验证商品库存
        skuStock(orderItem.getSpuId(), orderItem.getSkuId(), orderItem.getCount());
        ShopCartItemVO mainShopCartItem = conversionShopCartItem(orderItem, null, userId, addrId).get(0);
        if (orderItem.getCount() < 1) {
            orderItem.setCount(1);
        }
        //套餐商品id集合
        List<Long> spuIdList = new ArrayList<>(Constant.INITIAL_CAPACITY);
        spuIdList.add(orderItem.getSpuId());
        for (CartComboMatchSpuDTO cartComboMatchSpuDTO : orderItem.getCartComboMatchSpuDTOS()) {
            spuIdList.add(cartComboMatchSpuDTO.getSpuId());
        }
        //获取套餐商品信息
        ServerResponseEntity<List<SpuVO>> listServerResponseEntity = spuFeignClient.listSpuBySpuIds(spuIdList);
        if (!listServerResponseEntity.isSuccess()) {
            LOGGER.error("获取套餐商品信息失败：{}", listServerResponseEntity.getMsg());
            throw new LuckException(listServerResponseEntity.getMsg());
        }
        List<SpuVO> spuList = listServerResponseEntity.getData();
        Map<Long, List<SpuVO>> spuMap = spuList.stream().collect(Collectors.groupingBy(SpuVO::getSpuId));
        //套餐主商品信息
        SpuVO mainSpu = spuMap.get(orderItem.getSpuId()).get(0);
        if (!Objects.equals(mainSpu.getSupplierId(), 0L) && Objects.equals(mainSpu.getSupplierDeliveryType(), 1)) {
            mainShopCartItem.setSupplierId(mainSpu.getSupplierId());
        } else {
            mainShopCartItem.setSupplierId(0L);
        }
        mainShopCartItem.setIsMainProd(1);
        mainShopCartItem.setCount(orderItem.getCount());
        shopCartItems.add(mainShopCartItem);
        if (CollUtil.isNotEmpty(orderItem.getCartComboMatchSpuDTOS())) {
            //搭配商品处理
            for (CartComboMatchSpuDTO cartComboMatchSpuDTO : orderItem.getCartComboMatchSpuDTOS()) {
                ShopCartItemDTO matchingOrderItem = new ShopCartItemDTO();
                matchingOrderItem.setSkuId(cartComboMatchSpuDTO.getSkuId());
                matchingOrderItem.setComboId(orderItem.getComboId());
                matchingOrderItem.setCount(cartComboMatchSpuDTO.getCount());
                matchingOrderItem.setSpuId(cartComboMatchSpuDTO.getSpuId());
                ShopCartItemVO matchingShopCartItem = conversionShopCartItem(matchingOrderItem, null, userId, addrId).get(0);
                matchingShopCartItem.setIsMainProd(0);
                matchingShopCartItem.setParentCartItemId(0L);
                SpuVO matchSpu = spuMap.get(cartComboMatchSpuDTO.getSpuId()).get(0);
                if (!Objects.equals(matchSpu.getSupplierId(), 0L) && Objects.equals(matchSpu.getSupplierDeliveryType(), 1)) {
                    matchingShopCartItem.setSupplierId(matchSpu.getSupplierId());
                } else {
                    matchingShopCartItem.setSupplierId(0L);
                }
                shopCartItems.add(matchingShopCartItem);

                // 验证商品库存
                skuStock(matchingShopCartItem.getSpuId(), matchingOrderItem.getSkuId(), matchingOrderItem.getCount());
            }
        }
        for (ShopCartItemVO shopCartItem : shopCartItems) {
            shopCartItem.setComboId(orderItem.getComboId());
            shopCartItem.setComboCount(orderItem.getCount());
        }
        return shopCartItems;
    }

    private void skuStock(Long spuId, Long skuId, Integer count) {
        // 套餐商品直接购买时判断库存是否足够
        SkuVO skuVo = skuFeignClient.getById(skuId).getData();
        SpuVO spuVo = spuFeignClient.getById(spuId).getData();
        // 获取加购的sku库存
        Integer skuStock = null;
        if (count > 0) {
            // 判断下是否为供应商商品,如果是商家代销供应商商品且为供应商发货设置供应商信息
            if (!Objects.equals(spuVo.getSupplierId(), 0L) && Objects.equals(spuVo.getSupplierDeliveryType(), 1)) {
                LOGGER.info("商家代销供应商商品且为供应商发货，获取供应商商品库存");
                skuStock = skuStockFeignClient.getBySkuId(skuVo.getSupplierSkuId()).getData();
            } else {
                LOGGER.info("获取商家商品库存");
                skuStock = skuStockFeignClient.getBySkuId(skuId).getData();
            }
        }
        //判断商品库存是否足够
        if (count > 0 && count > skuStock) {
            LOGGER.error("商品规格库存不足");
            throw new LuckException(spuVo.getName() + "商品规格库存不足");
        }
    }

}
